#include "oled_iic.h"
#include <stdio.h>

#include "fond.h"

/**
 * @brief  OLED设置光标位置
 * @param  fd Linux的文件描述符
 * @param  X 以左上角为原点，向右方向的坐标，范围：0~127
 * @param  Y 以左上角为原点，向下方向的坐标，范围：0~7
 * @retval 无
 */
void OLED_SetCursor(int fd, uint8_t X, uint8_t Y)
{
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0xB0 + Y);                 // 设置页地址(0-7)
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0x10 | ((X & 0xF0) >> 4)); // 设置X位置高4位
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0x00 | (X & 0x0F));        // 设置X位置低4位
}

/**
 * @brief  OLED清屏
 * @param  fd Linux的文件描述符
 * @retval 无
 */
void OLED_Clear(int fd) // 清屏函数
{
    unsigned char i, n;
    for (i = 0; i < 8; i++)
    {
        OLED_SetCursor(fd, 0, i);
        for (n = 0; n < 128; n++)
            wiringPiI2CWriteReg8(fd, OLED_DATA, 0);
    } // 更新显示

    // int num = 'A'-' ';
    // OLED_SetCursor(fd,0,0);
    // for(int j = 0;j < 8;j++)
    //     wiringPiI2CWriteReg8(fd, OLED_DATA, asc_8X16[num][j]);
    // OLED_SetCursor(fd,0,1);
    // for(int j = 8;j < 16;j++)
    //     wiringPiI2CWriteReg8(fd, OLED_DATA, asc_8X16[num][j]);
}

/**
 * @brief  OLED填充函数
 * @param  fd Linux的文件描述符
 * @param  data 填充的数据
 * @retval 无
 */
void OLED_Fill(int fd, unsigned char data) // 清屏函数
{
    unsigned char i, n;
    for (i = 0; i < 8; i++)
    {
        OLED_SetCursor(fd, 0, i);
        for (n = 0; n < 128; n++)
            wiringPiI2CWriteReg8(fd, OLED_DATA, data);
    } // 更新显示
}

/**
 * @brief  OLED显示字符
 * @param  fd Linux的文件描述符
 * @param  x  光标行(0 ~ 127)
 * @param  y  光标列  小字体(0 ~ 7) 大字体(0~3)
 * @param  num 显示字符的ASCII
 * @param  size 字体大小(12\16\24)
 * @retval 无
 */
void OLED_Show_Char(int fd, int x, int y, int num, int size)
{
    int i, j, page;

    num = num - ' '; // 偏移
    page = size / 8;
    if (size % 8 > 0)
        page++;
    for (i = 0; i < page; i++)
    {
        OLED_SetCursor(fd, x, y + i);
        for (j = size / 2 * i; j < size / 2 * (i + 1); j++)
        {
            if (size == 12)
            {
                wiringPiI2CWriteReg8(fd, OLED_DATA, asc_6X12[num][j]);
            }
            else if (size == 16)
            {
                wiringPiI2CWriteReg8(fd, OLED_DATA, asc_8X16[num][j]);
            }
            else if (size == 24)
            {
                wiringPiI2CWriteReg8(fd, OLED_DATA, asc_12X24[num][j]);
            }
        }
    }
}

/**
 * @brief  OLED显示字符串
 * @param  fd Linux的文件描述符
 * @param  x  光标行(0 ~ 127)
 * @param  y  光标列  小字体(0 ~ 7) 大字体(0~3)
 * @param  str 需要显示的字符串
 * @param  size 字体大小(12\16\24)
 * @retval 无
 */
void OLED_Show_String(int fd, int x, int y, char *str, int size)
{
    while (*str != '\0')
    {
        OLED_Show_Char(fd, x, y, *str, size);
        x += size / 2;
        str++;
    }
}

void OLED_Init(int fd)
{
    delay(10);
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0x00); //---set low column address
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0x10); //---set high column address
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0x40); //--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0x81); //--set contrast control register
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0xCF); // Set SEG Output Current Brightness
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0xA1); //--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0xC8); // Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0xA6); //--set normal display
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0xA8); //--set multiplex ratio(1 to 64)
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0x3f); //--1/64 duty
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0xD3); //-set display offset	Shift Mapping RAM Counter (0x00~0x3F)
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0x00); //-not offset
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0xd5); //--set display clock divide ratio/oscillator frequency
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0x80); //--set divide ratio, Set Clock as 100 Frames/Sec
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0xD9); //--set pre-charge period
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0xF1); // Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0xDA); //--set com pins hardware configuration
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0x12);
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0xDB); //--set vcomh
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0x40); // Set VCOM Deselect Level
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0x20); //-Set Page Addressing Mode (0x00/0x01/0x02)
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0x02); //
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0x8D); //--set Charge Pump enable/disable
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0x14); //--set(0x10) disable
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0xA4); // Disable Entire Display On (0xa4/0xa5)
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0xA6); // Disable Inverse Display On (0xa6/a7)
    OLED_Clear(fd);
    wiringPiI2CWriteReg8(fd, OLED_CMD, 0xAF); /*display ON*/
}